/**
 * 解析 URL
 * 将 URL 转换为 object 格式
 *
 * @param {string} url
 * @returns {Object}
 */
export function analysisQueryString (url = window.location.href) {
  const search = url.substring(url.lastIndexOf('?') + 1);
  const obj = {};
  const reg = /([^?&=]+)=([^?&=]*)/g;

  search.replace(reg, (str, $1, $2) => {
    const key = decodeURIComponent($1);
    obj[key] = decodeURIComponent($2) + '';
    return str;
  });

  return obj;
}

/**
 * 讲一个对象转为 queryString
 *
 * { aa: 'aaa', bb: 'bbb' } -> "aa=aaa&bb=bbb"
 *
 * @param obj
 * @returns {string}
 */
export function toQueryString (obj) {
  if (!obj || typeof obj !== 'object') return '';
  return Object.entries(obj).map(item => {
    return item.reduce((prev, next) => {
      if (typeof next === 'object' && next !== null) return '';
      return `${encodeURIComponent(prev)}=${encodeURIComponent(next)}`;
    });
  }).join('&');
}

/**
 * Merges two objects, giving the last one precedence
 * 合并两个对象，使最后一个优先
 *
 * @param {Object} target
 * @param {(Object|Array)} source
 * @returns {Object}
 */
export function objectMerge (target, source) {
  if (typeof target !== 'object') {
    target = {};
  }

  if (Array.isArray(source)) {
    return source.slice();
  }

  Object.keys(source).forEach(property => {
    const sourceProperty = source[property];
    if (typeof sourceProperty === 'object') {
      target[property] = objectMerge(target[property], sourceProperty);
    } else {
      target[property] = sourceProperty;
    }
  });
  return target;
}

/**
 * 防抖函数
 *
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce (func, wait, immediate) {
  let timeout, args, context, timestamp, result;

  const later = function () {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp;

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  };

  return function (...args) {
    context = this;
    timestamp = +new Date();
    const callNow = immediate && !timeout;
    // 如果延时不存在，重新设定延时
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args);
      context = args = null;
    }

    return result;
  };
}

/**
 * This is just a simple version of deep copy
 * Has a lot of edge cases bug
 * 深拷贝
 *
 * If you want to use a perfect deep copy, use lodash's _.cloneDeep
 *
 * @param {Object} source
 * @returns {Object}
 */
export function deepClone (source) {
  if (!source && typeof source !== 'object') {
    throw new Error('error arguments deepClone');
  }
  const targetObj = (source instanceof Array ? [] : {});

  Object.keys(source).forEach(keys => {
    if (source[keys] && typeof source[keys] === 'object') {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys];
    }
  });

  return targetObj;
}

/**
 * 创建一个 map
 *
 * @param str
 * @param expectsLowerCase
 * @returns {{(*): *, (*): *}}
 */
export function makeMap (str, expectsLowerCase) {
  const map = Object.create(null);
  const list = str.split(',');
  for (let i = 0; i < list.length; i++) {
    map[list[i]] = true;
  }
  return expectsLowerCase
    ? val => map[val.toLowerCase()]
    : val => map[val];
}

/**
 * 验证是否为数字
 *
 * @param str
 * @returns {boolean}
 */
export function isNumberStr (str) {
  return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str);
}

/**
 * 清除数据中的 undefined 字段
 *
 * @param obj
 * @returns {any}
 */
export function clearUndefined (obj = {}) {
  return JSON.parse(JSON.stringify(obj));
}

/**
 * 获取数据类型
 *
 * getType([]) -> "[object Array]"
 *
 * @param target
 * @returns {string}
 */
export function toRawType (target) {
  return Object.prototype.toString.call(target);
}

/**
 * 获取对象的数据类型
 *
 * getType([]) -> "array"
 *
 * @param target 目标对象
 * @returns {string}
 */
export function getType (target) {
  return toRawType(target).slice(8, -1).toLowerCase();
}

/**
 * 判断数据类型
 *
 * isType({}, 'object') -> boolean
 *
 * @param target 目标对象
 * @param type   类型
 * @returns {boolean}
 */
export function isType (target, type) {
  return getType(target) === type;
}

/**
 * 去除 所有空格
 *
 * @param string
 * @returns {*}
 */
export function trimAll (string) {
  return string.replace(/(\s+)/g, '');
}

/**
 * 去除 两端的空格
 *
 * @param string
 * @returns {*}
 */
export function trim (string) {
  return string.replace(/(^\s+)|(\s+$)/g, '');
}

/**
 * 下划线转换驼峰式
 *
 * user_name -> userName
 *
 * @param string
 * @returns {*}
 */
export function camelCase (string) {
  return string.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
}

/**
 * 驼峰转换下划线
 *
 * @param string
 * @returns {string}
 */
export function lineCase (string) {
  return string.replace(/([A-Z])/g, '_$1').toLowerCase();
}

/**
 * 驼峰转换冒号
 *
 * @param string
 * @returns {string}
 */
export function colonCase (string) {
  return string.replace(/([A-Z])/g, ':$1').toLowerCase();
}

/**
 * 获取指定长度的随机数
 *
 * @returns {string}
 */
export function randomId (size = 7) {
  //随机码数组
  const codeArr = [
    'a','b','c','d','e','f','g','h','i','j','k','l','m','n',
    'o','p','q','r','s','t','u','v','w','x','y','z',
    'A','B','C','D','E','F','G','H','I','J','K','L','M','N',
    'O','P','Q','R','S','T','U','V','W','X','Y','Z',
    '0','1','2','3','4','5','6','7','8','9'
  ];

  let num = '';
  if (typeof size !== 'number') {
    size = 7;
  }

  for(let i = 0 ; i < size; i++) {
    num += codeArr[parseInt('' + Math.random() * 1000 % codeArr.length)];
  }

  return num;
}


/**
 * 车牌号码首位
 *
 * @returns {string}
 */
export function randomVehicleNo () {
  //随机码数组
  const codeArrFirst = [
    'A','B','C','D','E','F','G','H','I','J','K','L','M','N',
    'O','P','Q','R','S','T','U','V','W','X','Y','Z',
  ];
  //随机码数组
  const codeArr = [
    '京', '津', '沪', '渝', '蒙',
    '新', '藏', '宁', '桂', '港',
    '澳', '黑', '吉', '辽', '晋',
    '冀', '青', '鲁', '豫', '苏',
    '皖', '浙', '闽', '赣', '湘',
    '鄂', '粤', '琼', '甘', '陕',
    '黔', '滇', '川',
  ];

  return `${
    codeArr[parseInt('' + Math.random() * 100 % codeArrFirst.length)]
  }${
    codeArrFirst[parseInt('' + Math.random() * 100 % codeArrFirst.length)]
  }`;
}

/**
 * 获取指定最大长度的随机数
 * @param length
 * @returns {number}
 */
export function randomNumber (length = 6) {
  return parseInt('' + Math.random() * Math.pow(10, length));
}
